#import "SMRShadowTextField.h"
#import "SMRShadowTextFieldCell.h"
#import "NSAttributedString+SMRAdditions.h"
#import "SMROverlayShadowEffectView.h"


#pragma mark Constants
static NSString* const SMRShadowTextFieldEditingTextColorKey = @"SMRShadowTextFieldEditingTextColorKey";
static NSString* const SMRShadowTextFieldNormalTextColorKey = @"SMRShadowTextFieldNormalTextColorKey";
static NSString* const SMRShadowTextFieldShadowViewKey = @"SMRShadowTextFieldShadowViewKey";
static const CGFloat SMRShadowTextFieldEdgePadding = 3.0f;
static const CGFloat SMRShadowTextFieldBorderPaddingBezeled = 2.0f;
static const CGFloat SMRShadowTextFieldBorderPaddingNoBezel = 4.0f;


#pragma mark -
@interface SMRShadowTextField ()
@property (nonatomic, assign) BOOL overlayInnerRectNeedsUpdate;
@end


#pragma mark -
@interface SMRShadowTextField (SMRShadowTextFieldPrivateMethods)
-(void)commonInit_;
-(void)autoAdjustSize_;
-(SMRShadowTextFieldCell *)shadowCell_;
@end


#pragma mark -
@implementation SMRShadowTextField
@synthesize shadowView;
@synthesize overlayInnerRect;
@synthesize overlayInnerRectNeedsUpdate;


#pragma mark -
#pragma mark Initialization

+(Class)cellClass {
	return [SMRShadowTextFieldCell class];
}

-(id)initWithFrame:(NSRect)frameRect {
	if (!(self = [super initWithFrame:frameRect]))
		return nil;
	[self commonInit_];
	return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder {
	if (!(self = [super initWithCoder:aDecoder]))
		return nil;
	[self commonInit_];
	return self;
}

-(void)commonInit_ {
	[self setShadowView:[[SMROverlayShadowEffectView alloc] initWithFrame:NSZeroRect]];
	[[self shadowView] setBorderPadding:[self isBezeled] ? SMRShadowTextFieldBorderPaddingBezeled : SMRShadowTextFieldBorderPaddingNoBezel];
}


#pragma mark -
#pragma mark Pass-through for cell

-(void)setNormalColor:(NSColor *)aColor {
	[[self shadowCell_] setNormalColor:aColor];
}

-(NSColor *)normalColor {
	return [[self shadowCell_] normalColor];
}

-(void)setHighlightedColor:(NSColor *)aColor {
	[[self shadowCell_] setHighlightedColor:aColor];
}

-(NSColor *)highlightedColor {
	return [[self shadowCell_] highlightedColor];
}

-(void)setEditingColor:(NSColor *)aColor {
	[[self shadowCell_] setEditingColor:aColor];
}

-(NSColor *)editingColor {
	return [[self shadowCell_] editingColor];
}


#pragma mark -
#pragma mark NSTextField overrides

-(void)viewWillDraw {
	[super viewWillDraw];
	if ([self overlayInnerRectNeedsUpdate])
		[self updateOverlay];
}


#pragma mark -
#pragma mark Field editor delegate methods

-(void)textDidEndEditing:(NSNotification *)aNotification {
	[super textDidEndEditing:aNotification];
	[self hideEditModeBezel];
}

-(void)textDidChange:(NSNotification *)notification {
	[self setOverlayInnerRectNeedsUpdate:YES];
	[super textDidChange:notification];
}


#pragma mark -
#pragma mark Overlay support

-(void)showEditModeBezel {
	[self setOverlayInnerRectNeedsUpdate:YES];
	[self setNeedsDisplay:YES];
}

-(void)hideEditModeBezel {
	[[self shadowView] removeFromSuperview];
	[[self shadowCell_] setEditing:NO];
}

-(NSRect)overlayRectForRect:(NSRect)aRect {
	NSTextView *fieldEditor = (NSTextView *)[self currentEditor];
	NSAttributedString *currentString = nil;
	if ([fieldEditor isKindOfClass:[NSTextView class]]) 
		currentString = (NSAttributedString *)[fieldEditor textStorage];
	else 
		currentString = [self attributedStringValue];
	
	if ([self alignment] == NSRightTextAlignment)
		currentString = [currentString smrAttributedStringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
	CGFloat stringWidth = [currentString size].width;
	CGFloat adjustedWidth = stringWidth + (SMRShadowTextFieldEdgePadding * 2);
	if (adjustedWidth > [self bounds].size.width)
		adjustedWidth = [self bounds].size.width;
	aRect.size.width = adjustedWidth;
	aRect = [self centerScanRect:aRect];
	return aRect;
}

-(void)updateOverlay {
	if (![[self shadowCell_] editing])
		return;
	NSRect overlayRect = [self overlayRectForRect:[self visibleRect]];
	[self setOverlayInnerRect:overlayRect];
	[self setOverlayInnerRectNeedsUpdate:NO];
	
	if  ([[self shadowView] superview]) 
		[[self shadowView] updateOverlayRect:overlayRect];
	else 
		[[self shadowView] setOverlayRect:overlayRect inView:self];
}


#pragma mark -
#pragma mark Private methods

-(SMRShadowTextFieldCell *)shadowCell_ {
	return (SMRShadowTextFieldCell *)[self cell];
}

@end
